package org.kabeja.parser;

import org.kabeja.dxf.DXFDocument;
import org.kabeja.parser.dxf.DXFHandler;
import org.kabeja.parser.dxf.filter.DXFStreamFilter;

import java.io.*;
import java.util.*;

/**
 * @author shutao
 * @since 2022/4/25 14:25
 */
public class DXFParser implements HandlerManager, Handler, Parser, DXFHandler {
    public static final String PARSER_NAME = "DXFParser";
    public static final String EXTENSION = "dxf";
    private static final String SECTION_START = "SECTION";
    private static final String SECTION_END = "ENDSEC";
    private static final int COMMAND_CODE = 0;
    public static final String DEFAULT_ENCODING = "";
    protected DXFDocument doc;
    protected Map<String, Object> handlers = new HashMap<>();
    protected DXFSectionHandler currentHandler;
    protected List<Object> streamFilters = new ArrayList<>();
    protected DXFHandler filter;
    private boolean key = false;
    private boolean sectionstarts = false;
    private int linecount;
    private boolean parse = false;

    public DXFParser() {
    }

    @Override
    public void parse(String var1) throws ParseException {
        this.parse(var1, DEFAULT_ENCODING);
    }

    @Override
    public void parse(String var1, String var2) throws ParseException {
        try {
            this.parse(new FileInputStream(var1), var2);
        } catch (FileNotFoundException var4) {
            var4.printStackTrace();
        }
    }

    @Override
    public void parse(InputStream var1, String var2) throws ParseException {
        String var3 = DEFAULT_ENCODING;
        this.key = false;
        this.linecount = 0;
        this.parse = false;
        this.doc = new DXFDocument();
        this.doc.setProperty(DXFDocument.PROPERTY_ENCODING, var2);
        this.buildFilterChain();
        BufferedReader var4;

        if (var2 == null || DEFAULT_ENCODING.equals(var2)) {
            throw new ParseException("Encoding is empty!");
        }

        try {
            var4 = new BufferedReader(new InputStreamReader(var1, var2));

            this.key = true;
            this.sectionstarts = false;

            String line;
            while((line = var4.readLine()) != null) {
                ++this.linecount;
                if (this.key) {
                    var3 = line;
                    this.key = false;
                } else {
                    int var11 = Integer.parseInt(var3.trim());
                    this.filter.parseGroup(var11, new DXFValue(line.trim()));
                    this.key = true;
                }
            }

            var4.close();
            if (this.parse) {
                this.currentHandler.endSection();
            }

        } catch (IOException var9) {
            throw new ParseException(var9.toString());
        }
    }

    @Override
    public void parseGroup(int var1, DXFValue var2) throws ParseException {
        try {
            if (this.sectionstarts) {
                this.sectionstarts = false;
                if (this.handlers.containsKey(var2.getValue())) {
                    this.currentHandler = (DXFSectionHandler) this.handlers.get(var2.getValue());
                    this.parse = true;
                    this.currentHandler.setDXFDocument(this.doc);
                    this.currentHandler.startSection();
                } else {
                    this.parse = false;
                }

            } else {
                if (var1 == COMMAND_CODE && SECTION_START.equals(var2.getValue())) {
                    this.sectionstarts = true;
                }

                if (var1 == COMMAND_CODE && SECTION_END.equals(var2.getValue())) {
                    if (this.parse) {
                        this.currentHandler.endSection();
                    }

                    this.parse = false;
                } else {
                    if (this.parse) {
                        this.currentHandler.parseGroup(var1, var2);
                    }
                }
            }
        } catch (NumberFormatException var4) {
            var4.printStackTrace();
            throw new ParseException("Line: " + this.linecount + " unsupported groupcode: " + this.key + " for value:" + var2, var4);
        }
    }

    @Override
    public DXFDocument getDocument() {
        return this.doc;
    }

    public void addDXFSectionHandler(DXFSectionHandler var1) {
        var1.setDXFDocument(this.doc);
        this.handlers.put(var1.getSectionKey(), var1);
    }

    @Override
    public void addHandler(Handler var1) {
        this.addDXFSectionHandler((DXFSectionHandler)var1);
    }

    @Override
    public void releaseDXFDocument() {
        this.doc = null;
        for (Object o : this.handlers.values()) {
            Handler var2 = (Handler) o;
            var2.releaseDXFDocument();
        }

    }

    @Override
    public void setDXFDocument(DXFDocument var1) {
        this.doc = var1;
    }

    @Override
    public boolean supportedExtension(String var1) {
        return EXTENSION.equalsIgnoreCase(var1);
    }

    public void addDXFStreamFilter(DXFStreamFilter var1) {
        this.streamFilters.add(var1);
    }

    public void removeDXFStreamFilter(DXFStreamFilter var1) {
        this.streamFilters.remove(var1);
    }

    protected void buildFilterChain() {
        DXFHandler var1 = this;

        for(int var2 = this.streamFilters.size() - 1; var2 >= 0; --var2) {
            DXFStreamFilter var3 = (DXFStreamFilter)this.streamFilters.get(var2);
            var3.setDXFHandler(var1);
            var1 = var3;
        }

        this.filter = var1;
    }

    @Override
    public String getName() {
        return PARSER_NAME;
    }
}
